#!/bin/sh /etc/rc.common

START=55
SERVICE_USE_PID=1
SERVICE_WRITE_PID=1
SERVICE_DAEMONIZE=1
EXTRA_COMMANDS="firewall restart"

APP='chinadns'
BIN='/usr/bin/chinadns'
DNSMASQ_CONF='/etc/dnsmasq.conf'
IP_FAKE_FILE='/etc/ipset/fake'
IP_CHINA_FILE='/etc/ipset/china'
DNS_DEFAULT_PORT='53'

check_prerouting() {
	if iptables -t nat --list zone_lan_prerouting &>/dev/null; then
		PREROUTING='zone_lan_prerouting'
	else
		PREROUTING='PREROUTING'
	fi
}

iptables_flush() {
	iptables-restore <<-EOF
		$(iptables-save -t nat|grep -v "dport $DNS_DEFAULT_PORT ")
	EOF
	return $?
}

iptables_restore() {
	iptables-restore -n <<-EOF
		$(echo -e "$1")
	EOF
	return $?
}

mode_dnsmasq_enable() {
	grep -q "server=127.0.0.1#$local_port" "$DNSMASQ_CONF" || {
		echo -e "#${APP}_start\nno-resolv\nserver=127.0.0.1#$local_port\n#${APP}_end">>"$DNSMASQ_CONF"
		pidof dnsmasq &>/dev/null && /etc/init.d/dnsmasq restart
	}
}

mode_dnsmasq_disable() {
	FILE_DATA=$(cat "$DNSMASQ_CONF")
	FIND_START=$(echo -e "$FILE_DATA"|grep -n -x -m 1 "#${APP}_start")
	[ -z "$FIND_START" ] || {
		FIND_END=$(echo -e "$FILE_DATA"|grep -n -x -m 1 "#${APP}_end")
	}
	[ -z "$FIND_END" ] || {
		sed -i "${FIND_START%%:*},${FIND_END%%:*}d" "$DNSMASQ_CONF"
		pidof dnsmasq &>/dev/null && /etc/init.d/dnsmasq restart
	}
}

mode_udp_forward_enable() {
	[ -z "$PREROUTING" ] && check_prerouting
	IPTABLES_RULES="*nat\n"
	config_get tcp_forward config tcp_forward
	[ -z "$tcp_forward" ] || {
		if [ $tcp_forward -gt 0 ] && [ $tcp_forward -lt 65535 ]; then
			IPTABLES_RULES=$IPTABLES_RULES"-A $PREROUTING -p tcp --dport $DNS_DEFAULT_PORT -j DNAT --to-destination $tcp_forward\n"
		else
			DNS_TCP_FORWARD=$(echo "$tcp_forward"|grep -o '\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\(:[0-9]\{1,5\}\)\?')
			[ -z "$DNS_TCP_FORWARD" ] || {
				[ "${DNS_TCP_FORWARD##*:}" -gt "$DNS_TCP_FORWARD" ] && DNS_TCP_FORWARD=$DNS_TCP_FORWARD":53"
				IPTABLES_RULES=$IPTABLES_RULES"-A $PREROUTING -p tcp --dport $DNS_DEFAULT_PORT -j DNAT --to-destination $DNS_TCP_FORWARD\n"
			}
		fi
	}
	IPTABLES_RULES=$IPTABLES_RULES"-A $PREROUTING -p udp --dport $DNS_DEFAULT_PORT -j REDIRECT --to-ports $local_port\nCOMMIT"
	if iptables_restore "$IPTABLES_RULES"; then
		echo "Setting ... OK"
	else
		echo "Setting ... Failed"
		stop
	fi
}

mode_udp_forward_disable() {
	iptables_flush
}

mode() {
	case $mode in
		0)
			echo "Mode ... Normal"
			mode_udp_forward_disable
			mode_dnsmasq_disable
			;;
		1)
			echo "Mode ... Dnsmasq"
			mode_udp_forward_disable
			mode_dnsmasq_enable
			;;
		2)
			echo "Mode ... Forward"
			mode_dnsmasq_disable
			mode_udp_forward_enable
			;;
	esac
}

service_options() {
	config_get mode config mode '0'
	config_get dns_server config dns_server
	config_get local_port config local_port '5353'
	config_get delay_time config delay_time
	config_get IP_FAKE_FILE_enabled config IP_FAKE_FILE_enabled '1'
	config_get IP_CHINA_FILE_enabled config IP_CHINA_FILE_enabled '1'
	config_get compression config compression '0'
	config_get bidirectional config bidirectional '0'
	OPTIONS="-p $local_port"
	[ -z "$dns_server" ] || OPTIONS=$OPTIONS" -s $dns_server "
	[ -z "$delay_time" ] || OPTIONS=$OPTIONS" -y $delay_time"
	[ "$IP_FAKE_FILE_enabled" = '1' ] && OPTIONS=$OPTIONS" -l $IP_FAKE_FILE"
	[ "$IP_CHINA_FILE_enabled" = '1' ] && OPTIONS=$OPTIONS" -c $IP_CHINA_FILE"
	[ "$compression" = '1' ] && OPTIONS=$OPTIONS" -m"
	[ "$bidirectional" = '1' ] && OPTIONS=$OPTIONS" -d"
}

service_check() {
	FIND_DATA=$(ps|grep "$1"|grep -v "grep $1")
	[ -z "$FIND_DATA" ] && return 1
	return 0
}

service_process() {
	service_check "$1" && echo "Start $1 ... Already running. Please try \"stop\" or \"restart\"" && return 1
	service_start $1 $2
	service_check "$1" && echo "Start $1 ... OK" && return 0
	echo "Start $1 ... Fail" && return 1
}

start() {
	config_load "$APP"
	config_get enabled config enabled
	[ "$enabled" = '1' ] || exit
	service_options
	service_process "$BIN" "$OPTIONS" && mode && echo "Setting ... OK"
}

stop() {
	service_stop $BIN
	mode_dnsmasq_disable
	mode_udp_forward_disable
}

restart() {
	service_stop $BIN
	mode_udp_forward_disable
	start
}

firewall() {
	config_load "$APP"
	config_get mode config mode
	[ "$mode" = '2' ] && {
		config_get local_port config local_port '5353'
		mode_udp_forward_enable
	}
}
